﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using dw = System.Drawing;
using System.IO;
using System.Windows.Media.Imaging;
using System.Windows;
using System.Windows.Media;
using xnaGraphics = Microsoft.Xna.Framework.Graphics;
using xna = Microsoft.Xna.Framework;
using System.Windows.Controls;

namespace client.app
{
    public static class Extension
    {
        static gui2.IDrawCanvas FindDrawCanvas(FrameworkElement el)
        {
            object parent = el;
            while (parent != null)
            {
                if (parent is FrameworkElement)
                {
                    var p = (FrameworkElement)parent;
                    if (p is gui2.IDrawCanvas)
                    {
                        return (gui2.IDrawCanvas)p;
                    }
                    parent = p.Parent;
                }
            }
            return null;
        }

        public static void Draw(this dw.Bitmap bitmap, Action<dw.Graphics> draw, dw.Drawing2D.SmoothingMode mode = dw.Drawing2D.SmoothingMode.HighQuality)
        {
            using (var g = dw.Graphics.FromImage(bitmap))
            {
                g.SmoothingMode = mode;
                draw(g);
            }
        }
        public static void Save(this dw.Bitmap bitmap, Action<MemoryStream> save)
        {
            using (var ms = new MemoryStream())
            {
                bitmap.Save(ms, dw.Imaging.ImageFormat.Png);
                save(ms);
            }
        }

        public static void SetLeft(this FrameworkElement el, double left)
        {
            el.SetValue(Canvas.LeftProperty, left);
        }
        public static double GetLeft(this FrameworkElement el)
        {
            return (double)el.GetValue(Canvas.LeftProperty);
        }
        public static void SetTop(this FrameworkElement el, double top)
        {
            el.SetValue(Canvas.TopProperty, top);
        }
        public static double GetTop(this FrameworkElement el)
        {
            return (double)el.GetValue(Canvas.TopProperty);
        }
        public static void SetLeftTop(this FrameworkElement el, double left, double top)
        {
            SetLeft(el, left);
            SetTop(el, top);
        }
        public static Point GetLeftTop(this FrameworkElement el)
        {
            return new Point(GetLeft(el), GetTop(el));
        }
        public static void SetZIndex(this FrameworkElement el, int zIndex)
        {
            el.SetValue(Canvas.ZIndexProperty, zIndex);
        }
        public static int GetZIndex(this FrameworkElement el, int zIndex)
        {
            return (int)el.GetValue(Canvas.ZIndexProperty);
        }
        public static void UpDisplay(this FrameworkElement el, bool display)
        {
            var iw = FindDrawCanvas(el);
            if (iw != null)
            {
                iw.Display = display;
            }
        }
        public static void UpBeginDraw(this FrameworkElement el)
        {
            var iw = FindDrawCanvas(el);
            if (iw != null)
            {
                iw.BeginDraw();
            }
        }
        public static void SetRectClip(this FrameworkElement el)
        {
            el.Clip = new RectangleGeometry(new Rect(0, 0, el.Width, el.Height));
        }

        public static dw.Color Alpha(this dw.Color color, int alpha = 100)
        {
            return dw.Color.FromArgb((int)(255 / 100d * alpha), color);
        }
        public static dw.SolidBrush SolidBrush(this dw.Color color, int alpha = -1)
        {
            return new dw.SolidBrush(alpha == -1 ? color : color.Alpha(alpha));
        }
        public static dw.Pen Pen(this dw.Color color, int alpha = -1)
        {
            return new dw.Pen(alpha == -1 ? color.SolidBrush() : color.SolidBrush(alpha));
        }

        public static void FromBytes(this BitmapImage bitmapImage, byte[] bytes)
        {
            bitmapImage.BeginInit();
            bitmapImage.StreamSource = new MemoryStream(bytes);
            bitmapImage.EndInit();
        }
        public static void FromFile(this BitmapImage bitmapImage, string fileName)
        {
            bitmapImage.FromBytes(File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName)));
        }
        public static byte[] ToBitmap(this Visual target, out int[] size)
        {
            byte[] data = null;
            var bounds = VisualTreeHelper.GetDescendantBounds(target);
            int width = (int)bounds.Size.Width, height = (int)bounds.Size.Height;
            size = new int[] { width, height };
            if (width <= 0 || height <= 0)
            {
                return null;
            }
            var bitmap = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
            var dv = new DrawingVisual();
            using (var ctx = dv.RenderOpen())
            {
                var vb = new VisualBrush(target);
                ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
            }
            bitmap.Render(dv);

            data = new byte[width * height * 4];
            bitmap.CopyPixels(data, width * 4, 0);
            return data;
        }
        public static xnaGraphics.Texture2D ToTexture2D(this Visual target)
        {
            xnaGraphics.Texture2D tex = null;
            int[] size = null;
            var batmap = target.ToBitmap(out size);
            if (batmap != null)
            {
                int width = size[0], height = size[1];
                var pixels = new xna.Color[width * height];
                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        var id = width * 4 * y + x * 4;
                        var a = batmap[id + 3];
                        var r = batmap[id + 2];
                        var g = batmap[id + 1];
                        var b = batmap[id];
                        int offset = (y * width) + x;
                        pixels[offset] = new xna.Color(r, g, b, a);
                    }
                }
                tex = new xnaGraphics.Texture2D(MainGame.Instance.GraphicsDevice, width, height);
                tex.SetData<xna.Color>(pixels);
            }
            return tex;
        }

        public static void SetKeyColor(this xnaGraphics.Texture2D tex, xna.Color keyColor, xna.Color fillColor)
        {
            if (tex != null)
            {
                var pixels = new xna.Color[tex.Height * tex.Width];
                tex.GetData<xna.Color>(pixels);
                for (int h = 0; h < tex.Height; h++)
                {
                    for (int w = 0; w < tex.Width; w++)
                    {
                        int offset = ((h * tex.Width) + w);
                        if (pixels[offset] == keyColor)
                        {
                            pixels[offset] = fillColor;
                        }
                    }
                }
                tex.SetData<xna.Color>(pixels);
            }
        }
    }
}
